<template>
  <vxe-modal ref="modalRef" v-bind="getBindValue" v-model="openRef" :before-hide-method="beforeHideFn" @show="showEvent"
    @hide="hideEvent" @confirm="confirmEvent" @cancel="cancelEvent" @close="closeEvent" @zoom="zoomEvent"
    @resize="resizeEvent" @move="moveEvent">
    <template #title v-if="!$slots.title">
      <ModalHeader :helpMessage="getProps.helpMessage" :title="getMergeProps.title" @dblclick="titleDbClickEvent" />
    </template>

    <template #footer v-if="!$slots.footer">
      <ModalFooter v-bind="getMergeProps" @ok="okEvent" @cancel="cancelEvent">
        <template #[item]="data" v-for="item in Object.keys($slots)">
          <slot :name="item" v-bind="data || {}"></slot>
        </template>
      </ModalFooter>
    </template>

    <template #default>
      <div @keydown="keydownEvent" @keyup="keyupEvent" tabindex="0" style="height: 100%">
        <slot></slot>
      </div>
    </template>

    <!-- <template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
      <slot :name="item" v-bind="data || {}"></slot>
    </template> -->
  </vxe-modal>
</template>
<script lang="ts" setup>
import { computed, ref, watch, unref, watchEffect, useAttrs, getCurrentInstance } from 'vue';
import { VxeModal, VxeModalInstance, VxeModalDefines, ModalEventTypes } from 'vxe-pc-ui';

import { ModalProps, ModalMethods, VxeModalPropNames, ModalPropNames } from './typing';

import ModalFooter from './components/ModalFooter.vue';
import ModalHeader from './components/ModalHeader.vue';
import { isFunction, isNumber } from '@/utils/is';
// import { buildShortUUID } from '@/utils/uuid';
import { deepMerge } from '@/utils';
import { modalProps } from './props';
import { /* omit, */ pick } from 'lodash-es';

defineOptions({ name: 'AdVxeModal' });

const props = defineProps(modalProps);
const emit = defineEmits([
  'register',
  'open-change',
  'update:open',
  'show',
  'hide',
  'confirm',
  'cancel',
  'close',
  'zoom',
  'resize',
  'move',
  'ok',
  'keydown',
  'keyup',
]);
const attrs = useAttrs();
const modalRef = ref<VxeModalInstance>();
const openRef = ref(false);
const propsRef = ref<Partial<ModalProps> | null>(null);

const getMergeProps = computed((): ModalProps => {
  const mergeProps = {
    ...props,
    ...unref(propsRef),    
  };
  return mergeProps;
});

const getProps = computed((): ModalProps => {
  const opt = {
    ...unref(getMergeProps),
    // open: unref(openRef),
    cancelButtonProps: undefined,
    okButtonProps: undefined,
    title: undefined,
  };
  return {
    ...opt,
  };
});

const getBindValue = computed((): ModalProps => {
  const attr = {
    ...attrs,
    ...unref(getMergeProps),
  };
  return pick(attr, VxeModalPropNames);
});

const getMinWidth = computed(() => {
  let value = unref(getProps)?.minWidth;
  if (isNumber(value)) {
    return `${value}px`;
  } else {
    return value;
  }
});
const getMinHeight = computed(() => {
  let value = unref(getProps)?.minHeight;
  if (isNumber(value)) {
    return `${value}px`;
  } else {
    return value;
  }
});
const getMaxWidth = computed(() => {
  let value = unref(getProps)?.maxWidth;
  if (isNumber(value)) {
    return `${value}px`;
  } else {
    return value;
  }
});
const getMaxHeight = computed(() => {
  let value = unref(getProps)?.maxHeight;
  if (isNumber(value)) {
    return `${value}px`;
  } else {
    return value;
  }
});

// 弹窗对象
const getModal = computed(() => unref(modalRef));

const modalMethods: ModalMethods = {
  getModal: () => unref(getModal),
  isOpen: () => unref(openRef),
  setModalProps,
};

/**
 * @description: 设置modal参数
 */
function setModalProps(props: Partial<ModalProps>): void {
  // Keep the last setModalProps
  const propsTmp = pick(props, [...VxeModalPropNames, ...ModalPropNames]);
  propsRef.value = deepMerge(unref(propsRef) || ({} as any), propsTmp);
  if (Reflect.has(props, 'open')) {
    openRef.value = !!props.open;
  }
}

const instance = getCurrentInstance();
if (instance) {
  emit('register', modalMethods, instance.uid);
}

watchEffect(() => {
  openRef.value = !!props.open;
});

watch(
  () => unref(openRef),
  (v) => {
    emit('open-change', v);
    emit('update:open', v);
    if (v) {
      const boxElement = getModal.value?.getBox();
      if (boxElement) {
        if (getMinWidth.value) {
          boxElement.style.minWidth = getMinWidth.value;
        } else {
          boxElement.style.removeProperty('min-width');
        }
        if (getMinHeight.value) {
          boxElement.style.minHeight = getMinHeight.value;
        } else {
          boxElement.style.removeProperty('min-height');
        }
        if (getMaxWidth.value) {
          boxElement.style.maxWidth = getMaxWidth.value;
        } else {
          boxElement.style.removeProperty('max-width');
        }
        if (getMaxHeight.value) {
          boxElement.style.maxHeight = getMaxHeight.value;
        } else {
          boxElement.style.removeProperty('max-height');
        }
      }
    }
  },
  {
    immediate: false,
  },
);

/** 弹窗标题双击事件 */
async function titleDbClickEvent() {
  // if (props.showZoom) {
  //   await getModal.value?.zoom();
  // }
}

/** 在窗口隐藏之前执行，可以返回 Error 阻止关闭，支持异步。点击关闭，或者按 ESC 键之前可以拦截。 */
async function beforeHideFn(params: { type: ModalEventTypes }) {
  if (props.closeFunc && isFunction(props.closeFunc)) {
    const isClose: boolean = await props.closeFunc(params);
    // openRef.value = !isClose;
    // return;
    if (!isClose) {
      return new Error();
    }
  }
}

/** 在窗口显示时会触发该事件 */
async function showEvent(e: VxeModalDefines.ShowEventParams) {
  emit('show', e);
}
/** 在窗口隐藏时会触发该事件 */
async function hideEvent(e: VxeModalDefines.HideEventParams) {
  emit('hide', e);
}
/** 点击确定按钮时会触发该事件 */
async function confirmEvent(e: VxeModalDefines.ConfirmEventParams) {
  emit('confirm', e);
}
/** 取消事件 */
async function cancelEvent(e: Recordable) {
  openRef.value = false;
  emit('cancel', e);
}
/** 点击关闭按钮时会触发该事件 */
async function closeEvent(e: VxeModalDefines.CloseEventParams) {
  emit('close', e);
}
/** 窗口缩放时会触发该事件 */
async function zoomEvent(e: VxeModalDefines.ZoomEventParams) {
  const boxElement = getModal.value?.getBox();
  if (boxElement) {
    if (e?.type.toLowerCase() === 'minimize') {
      boxElement.style.removeProperty('min-width');
    } else {
      if (getMinWidth.value) {
        boxElement.style.minWidth = getMinWidth.value;
      }
    }
  }
  emit('zoom', e);
}
/** 窗口调整大小时会触发该事件 */
async function resizeEvent(e: VxeModalDefines.ResizeEventParams) {
  emit('resize', e);
}
/** 窗口移动时会触发该事件 */
async function moveEvent(e: VxeModalDefines.MoveEventParams) {
  emit('move', e);
}
/** 确认事件 */
function okEvent(e: Recordable) {
  // openRef.value = false;
  emit('ok', e);
}
/** 键盘按下时会触发该事件 */
async function keydownEvent(e: KeyboardEvent) {
  emit('keydown', e);
}
/** 键盘弹起时会触发该事件 */
async function keyupEvent(e: KeyboardEvent) {
  emit('keyup', e);
}
</script>

<style lang="less">
// .vxe-modal--wrapper .vxe-modal--content {
//   padding: 0;
// }
//解决ant组件被遮挡问题
.ant-select-dropdown {
  z-index: 999999999;
}

.ant-cascader-dropdown {
  z-index: 999999999;
}

.ant-select-tree-list {
  z-index: 999999999;
}

.ant-picker-dropdown {
  z-index: 999999999;
}

.ant-dropdown {
  z-index: 999999999;
}

.ant-message {
  z-index: 999999999;
}

.ant-tooltip {
  z-index: 999999999;
}
</style>
